#include "VerifyGrpcClient.h"

GRPConPool::GRPConPool(size_t poolSize, std::string host, std::string port) :
	_pool_size(poolSize), _host(host), _port(port), _b_stop(false) {

	for (size_t i = 0; i < _pool_size; i++) {
		std::shared_ptr<Channel> channel = grpc::CreateChannel(host + ":" + port,
			grpc::InsecureChannelCredentials());
		_connection.push(VarifyService::NewStub(channel));
	}
}

GRPConPool::~GRPConPool() {
	std::lock_guard<std::mutex> lock(_mutex);
	while (!_connection.empty()) {
		_connection.pop();
	}
}

void GRPConPool::Close() {
	_b_stop = true;
	_cond.notify_all();
}

std::unique_ptr<VarifyService::Stub> GRPConPool::getConnection() {
	std::unique_lock<std::mutex> lock(_mutex);
	_cond.wait(lock, [this]() {
		if (_b_stop) {
			return true;
		}
		return !_connection.empty();
		});

	if (_b_stop) {
		return nullptr;
	}

	auto context = std::move(_connection.front());
	_connection.pop();
	return context;
}

void GRPConPool::returnConnection(std::unique_ptr<VarifyService::Stub> context) {
	std::lock_guard<std::mutex> lock(_mutex);
	if (_b_stop) {
		return;
	}

	_connection.push(std::move(context));
	_cond.notify_one();
}

VerifyGrpcClient::VerifyGrpcClient() {
	auto& gCfgMgr = ConfigMgr::Inst();
	std::string host = gCfgMgr["VarifyServer"]["Host"];
	std::string port = gCfgMgr["VarifyServer"]["Port"];
	_pool.reset(new GRPConPool(5, host, port));
}

GetVarifyRsp VerifyGrpcClient::GetVerifyCode(std::string email) {
	ClientContext context;
	GetVarifyRsp reply;
	GetVarifyReq request;

	request.set_email(email);

	auto stub = _pool->getConnection();
	Status status = stub->GetVarifyCode(&context, request, &reply);

	if (!status.ok()) {
		_pool->returnConnection(std::move(stub));
		reply.set_error(ErrorCodes::RECFailed);
	}

	return reply;
}

